<?php
namespace Kuoqi\DbDriver;
use \Kuoqi\Config;
use Kuoqi\Error;

//pdo版本的数据库驱动对象
//这个负责组装出最后的SQL语句，所以所有的基础设置都在这里面进行
class SqlDriver{
	
	static protected $TARGET_TYPE ;	
	static protected $DB_HOST;//链接的服务地址
	static protected $DB_PORT;//链接端口号
	static protected $DB_NAME;//链接的数据库名
	static protected $DB_USER;//链接的用户名
	static protected $DB_PASS;//链接的密码
    static protected $DB_DRIVER_QUERY = null;//数据库驱动信息
	

	public $_ATTR_PERSISTENT = false;//是否永久链接
	public $_BACK_SQL = false;//是否返回sql语句，用于语句自查，子语句等相关场景
	public $hasCache = 0;//是否启用缓存
	public $charset = 'UTF8';
	public $prefix = '';//表前缀
	public $dbdriver = null;//数据库原始的内容部分
	public $sqldriver = null;//sql部分
	public $objfield = null;//字段的驱动对象
	public $objtable = null;//table的驱动处理
	public $objwhere = null;//where条件的驱动
	public $objgroup = null;//分组查询的数组
	public $objorder = null;//排序的数组
	public $objlimit = null;//limit的相关处理
	public $objdata = null;//
	public $objjoin = null;
	public function __construct(){
		$this->prefix =  Config::get('DB_PREFIX');//配置表前缀
		$this->charset = Config::get('DB_CHARSET');
	}
	
	//字符串安全转换
	protected function stringSecure($str){
		return str_replace('"',"'",$str);
	}
	
	//获取数据库名称
	public function getDbname(){
		return self::$DB_NAME;	
	}
	
	
	//待链接的膜表数据库类型
	public function target($target_type){
		self::$TARGET_TYPE = strtolower($target_type);
	}
	
	//执行链接的函数
	public function connect($dbhost = null, $dbport = null, $dbname = null, $dbuser = null, $dbpass = null){
		if($dbhost){
			//如果配置了一个值，那么就要配置所有的值
			self::$DB_HOST = $dbhost;
			self::$DB_PORT = $dbport;
			self::$DB_NAME = $dbname;
			self::$DB_USER = $dbuser;	
			self::$DB_PASS = $dbpass;
		}else{
			self::$DB_HOST = Config::get('DB_HOST');
			self::$DB_PORT = Config::get('DB_PORT');
			self::$DB_NAME = Config::get('DB_NAME');
			self::$DB_USER = Config::get('DB_USER');
			self::$DB_PASS = Config::get('DB_PSD');
		}
		
		//这个地方实现具体的逻辑
		switch(self::$TARGET_TYPE){
			case 'mysql':return $this->doMysqlConnect();//执行链接mysql数据库的模式
			default:throw new \Kuoqi\Error('目标服务器['.self::$TARGET_TYPE.']暂不支持数据库链接');
		}
	}
	
	//链接mysql服务器
	public function doMysqlConnect(){
        //$conn = new \PDO('odbc:Driver={SQL Server};Server=localhost;Database=mysql','root','123456');
		$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s'
			,self::$DB_HOST
			,self::$DB_PORT
			,self::$DB_NAME
			);
		try{
		    //todo--已经具备多个数据库链接的条件，可以尝试扩展了哈
		    if(self::$DB_DRIVER_QUERY==null){
                self::$DB_DRIVER_QUERY = new \PDO($dsn,self::$DB_USER,self::$DB_PASS,array(
                    \PDO::ATTR_ERRMODE,\PDO::ERRMODE_SILENT
                ));
                self::$DB_DRIVER_QUERY->setAttribute(\PDO::ATTR_ERRMODE,$this->_ATTR_PERSISTENT);
                $this->query("set names ".$this->charset);
            }
			return $this;
		}catch(\Kuoqi\Error $err){
		    throw new $err();
		}
	}

    /**
     * cache缓存模块的所有信息
     * @param $time
     * @return $this
     */
	public function cache($time){
		$this->hasCache = intval($time);
		return $this;
	}
	
	public function join($rex, $condition = ''){
	    if($this->objjoin){
            $this->objjoin->input($rex,$condition);
        }else{
            $this->objjoin = new Sql\Join();
            $this->objjoin->input($rex,$condition);
        }
		return $this;
	}

	//是否返回sql语句，用于语句自查，子语句等相关场景
	public function fetchSql($isSql = false){
		$this->_BACK_SQL = $isSql;
		return $this;	
	}
	
	//传入字段的方法定义
	public function field($params){
		$this->objfield = new Sql\Field($params);
		return $this;
	}
	
	//实现table的实现方法
	//传入两个参数，第一个为table的名称
	//传入两个参数，第二个为table的别名
	//返回为当前对象
	public function table($tbname,$tbalias = ''){
		$this->objtable = new Sql\Table($tbname,$tbalias);
		return $this;	
	}
	
	//简单的配置表别称
	public function alias($tbaslas){
		$this->objtable->alias = $tbaslas;
		return $this;	
	}
	
	//data，增加数据或者修改数据的数据写入
	public function data($data){
		$this->objdata = new Sql\Data($this);
		$this->objdata->input($data);	
		return $this;
	}
	//andData,增加或者修改数据的时候去已经有的数据中追加数据的操作，没有数据则重建
	public function andData($data){
		if(!$this->objdata){
			$this->objdata = new Sql\Data($this);
		}	
		$this->objdata->input($data);
		return $this;
	}
	
	//where条件对象
	//传入参数为条件对象[condition]
	//返回为当前对象驱动
	public function where($condition){
		$this->objwhere = new Sql\Where();
		$this->objwhere->input($condition);//处理内容
		return $this;	
	}
	
	//andwhere
	public function andWhere($condition){
		if($this->objwhere){
			$this->objwhere->input($condition);//处理内容	
		}else{
			$this->objwhere = new Sql\Where();
			$this->objwhere->input($condition);//处理内容	
		}
	}
	
	
	//执行sql的方法
	public function query($sql){
		return self::$DB_DRIVER_QUERY->query($sql);
	}
	
	
		
	public function group($code){
	   $this->objgroup = 'GROUP BY '.str_replace('"','\"',$code);
	   return $this;
    }
	
	//数据库排序
	public function order($code){
		$this->objorder = 'ORDER BY '.str_replace('"','\"',$code);	
		return $this;
	}

    /**
     * 数据库限制
     * createby kuoqi at 2022/8/15 10:42
     * @param $offset
     * @param int $count
     * @return $this
     * @throws Error
     */
	public function limit($offset,$count = 0){
		if(is_string($offset)){
			$offset = intval($offset);
		}else if(is_array($offset)){
			if(count($offset)!=2){
				throw new \Kuoqi\Error('limit数组只支持两个值');
			}
			$count = $offset[1];
			$offset = $offset[0];
				
		}
		
		$this->objlimit = sprintf('LIMIT %s%s',
			$offset,//offset
			($count>0)?','.$count:''//count
		);
		return $this;	
	}
	
	
	//数据库结果类-insert 的别称
	public function add($datas = array()){
		return $this->insert($datas);	
	}
	
		//数据库结果类-update的别称
	public function save($datas = array()){
		return $this->update($datas);	
	}
	
	/**
	* remark:getField数据单字段查询
	*/
	public function getField($kname){
		$fields = $this->field($kname)->find();
		if($this->_BACK_SQL){
			return $fields;
		}else{
			return $fields[$kname];	
		}
	}
	
	/**
	* remark:setField数据单字段设置
	*/
	public function setField($kname,$kvalue){
		return $this->data(array($kname=>$kvalue))->update();
	}
	
	/**
	* remark:getOne数据单字段查询
	*/
	public function getOne($kname){
		return $this->getField($kname);
	}
	
	/**
	* remark:setOne数据单字段设置
	*/
	public function setOne($kname,$kvalue){
		return $this->setField($kname,$kvalue);
	}
	
	//数据库结果类-删除 同delete
	public function del($andWhere = array()){
		return $this->delete($andWhere);	
	}
	
	//limit将失效
	public function paginate($pager = '',$count = NULL){
		if(!$count){$count = Config::get('DB_PAGE_COUNT');}
		if(!$pager){
			$pager = I(Config::get('DB_PAGE_VAR'),Config::get('DB_PAGE_PAGER'));	
		}
		if($pager<1){ $pager = 1;}
		$output = array();
		$output['totalCount'] = $this->count();
		$this->limit(($pager-1)*$count,$count);
		$output['data'] = $this->select();
		$output['pageNow'] = $pager;
		$output['pageCount'] = $count;
		$page = new Sql\Page();
		$page->Pager = $pager;
		$page->PageCount  = $count;
		$page->TotalCount = $output['totalCount'];
		if($pager==1){
			$output['hasPrev'] = false;
		}else{
			$output['hasPrev'] = true;
		}
		if($pager*$count<$output['totalCount']){
			$output['hasNext'] = true;
		}else{
			$output['hasNext'] = false;
		}
		$output['pager'] = $page->create();
		return $output;
	}
	
	/**
	* remark:开始事务
	*/
	public function startTrans(){
	   throw new Error('开发【Db->find】请在具体的驱动器里面实现');
    }
	/**
	* remark:回滚数据
	*/
    public function rollBack(){
        throw new Error('开发【Db->rollBack】请在具体的驱动器里面实现');
    }
	/**
	* remark:提交数据
	*/
    public function commit(){
        throw new Error('开发【Db->commit】请在具体的驱动器里面实现');
    }
	
	
	
}